package com.project.im.web.filter;

import com.project.im.app.dto.WebUserDetails;
import com.project.im.common.enums.ResponseCode;
import com.project.im.common.exception.WebAuthenticationException;
import com.project.im.common.util.JwtUtils;
import com.project.im.common.util.SecurityUtils;
import com.project.im.web.service.TokenService;
import com.project.im.web.service.WebUserDetailService;
import io.jsonwebtoken.Claims;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

@Component
@RequiredArgsConstructor
public class AuthWebFilter extends OncePerRequestFilter {
    private final TokenService tokenService;
    private final WebUserDetailService webUserDetailService;

    private static final String BEARER = "Bearer ";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String authorization = request.getHeader(HttpHeaders.AUTHORIZATION);
        if (!StringUtils.startsWithIgnoreCase(authorization, BEARER)) {
            throw new WebAuthenticationException(ResponseCode.AR104);
        }
        String token = authorization.substring(BEARER.length());
        Claims claims = tokenService.parseToken(token);
        if (claims == null) {
            throw new WebAuthenticationException(ResponseCode.AR101);
        }
        if (tokenService.isTokenExpired(claims)) {
            throw new WebAuthenticationException(ResponseCode.AR102);
        }
        String username = JwtUtils.extractSubject(claims);
        if (StringUtils.isBlank(username)) {
            throw new WebAuthenticationException(ResponseCode.AR101);
        }
        WebUserDetails userDetails = (WebUserDetails) webUserDetailService.loadUserByUsername(username);
        if (userDetails == null) {
            throw new WebAuthenticationException(ResponseCode.AR103);
        }
        SecurityUtils.setAuthentication(userDetails);
        filterChain.doFilter(request, response);
    }

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
        String authorization = request.getHeader(HttpHeaders.AUTHORIZATION);
        return StringUtils.isBlank(authorization);
    }
}
